/*  -*- mode: c++; coding: utf-8; c-file-style: "stroustrup"; -*-

    Copyright 2008 Asier Aguirre <asier.aguirre@gmail.com>
    This file is part of Intromit.

    Intromit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Intromit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Intromit.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef STRING_HH
#define STRING_HH
//! \addtogroup util
//@{

#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

//! Lightweight string utilities class
class string
{
    // ctor/init variables
    char **str;
    int n_str, n_str_max;

    // status variables

    // private functions
    void reserve_memory(int index_to_be_used, int str_size=-1);

    // internal
    void ctor();
    void dtor();

public:
    string();
    ~string();

    // return (volatile) string (do NOT free) to escaped string orig
    char *escape(const char *orig);
    char *escape_volatile(const char *orig);

    // return volatile string (do NOT free) formatted as desired
    char *format(const char *format, ...);
    char *format_volatile(const char *format, ...);
    char *format_volatile_va(const char *format, va_list ap);

    // get/set frame
    int get_frame();
    void set_frame(int f);
    void reset_frame();

    // regex
    static char *regex(const char *expression, char *string, int group=0); // may destroy string
    // returns position and len
    static int regex_indexes(const char *expression, char *string, int group=0, int *len=NULL);
    static void test_regex(char *expression, char *string);
    static bool regex_subst(const char *expression, const char *new_substring, char *string, int max_string);

    // search out of blocks: block_pairs is a string like "()\"\"<>"
    static char *search(char *string, char *needle, char *block_pairs);

    // compare two strings but ignoring space differences
    // n_string2 is an output parameter with the position of string2 when position of
    //           string1 is n_string1 (only when matched)
    static int strcmp_nospc(char *string1, char *string2);
    static int strcmp_nospc(char *string1, char *string2, char stop_at_this_character);
    static int strncmp_nospc(char *string1, char *string2, int n_string1, int *n_string2=NULL);
};

//! Fast/lightweight string indexer
class string_index
{
    // string storage
    char *doc;
    int n_doc, max_doc;

    // index to strings in doc (so that strings are sorted)
    int *index;
    int n_index, max_index;

    // private functions
    int search_nearest_index(char *str);

public:
    string_index();
    ~string_index();

    // returns position of string or -1 if string not in pool (i_doc)
    // makes a dicotomic search over index
    // in the case of prefix string, searched string must start by prefix
    int search_string(char *str);
    int search_prefix_string(char *prefix);

    // returns index of string or -1 if string not in pool (i_index)
    int search_string_index(char *str);
    int search_string_index_format(const char *format, ...);
    int search_prefix_string_index(char *prefix);

    // returns index of newly created string or the index of existing replica
    int search_add_string(char *str);
    int search_add_string_format(const char *format, ...);

    // returns the string by doc index or NULL if i_doc==-1
    char *string(int i_doc);

    // returns the string by index index
    inline int n_string() {return n_index;}
    char *i_string(int index_idx);

    // delete string
    void delete_string(int i_index);

    // doc/n_doc
    inline char *get_doc() {return doc;}
    inline int get_n_doc() {return n_doc;}

    // interchange info between string index objects
    void interchange(string_index &doc);

    // debug
    void dump(FILE *arch=stdout);
};

//@}
#endif

/* Offline metadata attributes:

   @metadata_attrs(
	string, string_index:
					~select
   )
*/
